winsafe\kernel\handles/handle_traits.rs
1#![allow(non_snake_case)]
2
3use std::{fmt, hash};
4
5/// A native
6/// [handle](https://learn.microsoft.com/en-us/windows/win32/sysinfo/handles-and-objects),
7/// implemented by all handle types.
8///
9/// Prefer importing this trait through the prelude:
10///
11/// ```no_run
12/// use winsafe::prelude::*;
13/// ```
14pub trait Handle:
15 Sized
16 + PartialEq
17 + Eq
18 + Send
19 + hash::Hash
20 + fmt::Debug
21 + fmt::Display
22 + fmt::LowerHex
23 + fmt::UpperHex
24{
25 /// The null, uninitialized handle; equals to `0`.
26 const NULL: Self;
27
28 /// The invalid handle; equals to `-1`.
29 ///
30 /// Operations upon this handle will fail with
31 /// [`ERROR::INVALID_HANDLE`](crate::co::ERROR::INVALID_HANDLE) error code.
32 const INVALID: Self;
33
34 /// Creates a new handle object by wrapping a pointer.
35 ///
36 /// This method can be used as an escape hatch to interoperate with other
37 /// libraries.
38 ///
39 /// # Safety
40 ///
41 /// Be sure the pointer has the correct type and isn't owned by anyone else,
42 /// otherwise you may cause memory access violations.
43 #[must_use]
44 unsafe fn from_ptr(p: *mut std::ffi::c_void) -> Self;
45
46 /// Returns a raw copy of the underlying handle pointer.
47 ///
48 /// # Safety
49 ///
50 /// As the name implies, `raw_copy` returns a raw copy of the handle, so
51 /// closing one of the copies won't close the others. This means a handle
52 /// can be used after it has been closed, what can lead to errors and
53 /// undefined behavior. Even worse: sometimes Windows reuses handle values,
54 /// so you can call a method on a completely different handle type, what can
55 /// be catastrophic.
56 ///
57 /// However, in some cases the Windows API *demands* a copy of the handle –
58 /// `raw_copy` is an escape hatch to fill this gap.
59 #[must_use]
60 unsafe fn raw_copy(&self) -> Self {
61 Self::from_ptr(self.ptr())
62 }
63
64 /// Returns a mutable reference to the underlying raw pointer.
65 ///
66 /// This method can be used as an escape hatch to interoperate with other
67 /// libraries.
68 ///
69 /// # Safety
70 ///
71 /// This method exposes the raw pointer used by raw Windows calls. It's an
72 /// opaque pointer to an internal Windows structure, and no dereferencings
73 /// should be attempted.
74 #[must_use]
75 unsafe fn as_mut(&mut self) -> &mut *mut std::ffi::c_void;
76
77 /// Returns the underlying raw pointer.
78 ///
79 /// This method exposes the raw pointer used by raw Windows calls. It's an
80 /// opaque pointer to an internal Windows structure, and no dereferencings
81 /// should be attempted.
82 ///
83 /// This method can be used as an escape hatch to interoperate with other
84 /// libraries.
85 #[must_use]
86 fn ptr(&self) -> *mut std::ffi::c_void;
87
88 /// Returns `None` if the handle is null or invalid, otherwise returns
89 /// `Some(&self)`.
90 ///
91 /// # Examples
92 ///
93 /// ```no_run
94 /// use winsafe::{self as w, prelude::*};
95 ///
96 /// let hfile = w::HFILE::NULL;
97 ///
98 /// match hfile.as_opt() {
99 /// Some(hfile) => println!("Never prints"),
100 /// None => println!("The handle is null"),
101 /// }
102 /// ```
103 #[must_use]
104 fn as_opt(&self) -> Option<&Self> {
105 if *self == Self::NULL || *self == Self::INVALID {
106 None
107 } else {
108 Some(self)
109 }
110 }
111}